home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / C⁄C++ / Xconq 7.0d37 / source / kernel / ai.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-02  |  9.5 KB  |  478 lines  |  [TEXT/KAHL]

  1. /* Functions common to all AIs.
  2.    Copyright (C) 1992, 1993, 1994 Stanley T. Shebs.
  3.  
  4. Xconq is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2, or (at your option)
  7. any later version.  See the file COPYING.  */
  8.  
  9. #include "conq.h"
  10.  
  11. #include "mplay.h"
  12.  
  13. /* (should make "real" objects for each AI type) */
  14.  
  15. char *aitypenames[] = {
  16.   "brainless",
  17.   "mplayer",
  18.   NULL
  19. };
  20.  
  21. void
  22. init_ai(side)
  23. Side *side;
  24. {
  25.     if (side_wants_ai(side)) {
  26.     if (strcmp("mplayer", side->player->aitypename) == 0) {
  27.         mplayer_init(side);
  28.     } else {
  29.     }
  30.     if (!side_has_ai(side)) {
  31.         init_warning("might not have made an AI (type %s) for %s",
  32.              side->player->aitypename, side_desig(side));
  33.     }
  34.     }
  35. }
  36.  
  37. /* Change the AI running a side.  This has to clean up if the AI is
  38.    being turned off. */
  39.  
  40. void
  41. set_side_ai(side, typename)
  42. Side *side;
  43. char *typename;
  44. {
  45.     Unit *unit;
  46.  
  47.     if (typename == NULL) {
  48.     side->player->aitypename = NULL;
  49.     /* (should just deactivate) */
  50.     side->ai = NULL;
  51.     /* Clear out everything that was set up by the AI. */
  52.     for_all_side_units(side, unit) {
  53.         unit->aihook = NULL;
  54.         if (unit->plan && unit->plan->aicontrol) {
  55.         unit->plan->type = PLAN_NONE;
  56.         unit->plan->maingoal = NULL;
  57.         unit->plan->formation = NULL;
  58.         unit->plan->funit = NULL;
  59.         clear_task_agenda(unit->plan);
  60.         unit->plan->asleep = FALSE;
  61.         unit->plan->reserve = FALSE;
  62.         /* Don't touch delay, let action looping clear it eventually. */
  63.         unit->plan->aicontrol = FALSE;
  64.         }
  65.         /* Still let units finish their currently buffered action. */
  66.     }
  67.     } else {
  68.     side->player->aitypename = typename;
  69.     for_all_side_units(side, unit) {
  70.         unit->aihook = NULL;
  71.         if (unit->plan && unit->plan->aicontrol) {
  72.         unit->plan->type = PLAN_NONE;
  73.         unit->plan->maingoal = NULL;
  74.         unit->plan->formation = NULL;
  75.         unit->plan->funit = NULL;
  76.         clear_task_agenda(unit->plan);
  77.         unit->plan->aicontrol = TRUE;
  78.         }
  79.         /* Still let units finish their currently buffered action. */
  80.     }
  81.     init_ai(side);
  82.     }
  83. }
  84.  
  85. void
  86. ai_init_turn(side)
  87. Side *side;
  88. {
  89.     switch (side_ai_type(side)) {
  90.       case nobrains:
  91.     break;
  92.       case mplayertype:
  93.     mplayer_init_turn(side);
  94.     break;
  95.       default:
  96.     case_panic("player AI type", side_ai_type(side));
  97.     break;
  98.     }
  99. }
  100.  
  101. void
  102. ai_decide_plan(side, unit)
  103. Side *side;
  104. Unit *unit;
  105. {
  106.     switch (side_ai_type(side)) {
  107.       case nobrains:
  108.     unit->plan->type = PLAN_PASSIVE;
  109.     clear_task_agenda(unit->plan);
  110.     break;
  111.       case mplayertype:
  112.     mplayer_decide_plan(side, unit);
  113.     break;
  114.       default:
  115.     case_panic("player AI type", side_ai_type(side));
  116.     break;
  117.     }
  118. }
  119.  
  120. void
  121. ai_react_to_unit_loss(side, unit)
  122. Side *side;
  123. Unit *unit;
  124. {
  125.     switch (side_ai_type(side)) {
  126.       case nobrains:
  127.     break;
  128.       case mplayertype:
  129.     mplayer_react_to_unit_loss(side, unit);
  130.     break;
  131.       default:
  132.     case_panic("player AI type", side_ai_type(side));
  133.     break;
  134.     }
  135. }
  136.  
  137. /* Forward an action result to the appropriate AI routine. */
  138.  
  139. void
  140. ai_react_to_action_result(side, unit, rslt)
  141. Side *side;
  142. Unit *unit;
  143. int rslt;
  144. {
  145.     switch (side_ai_type(side)) {
  146.       case nobrains:
  147.     break;
  148.       case mplayertype:
  149.     mplayer_react_to_action_result(side, unit, rslt);
  150.     break;
  151.       default:
  152.     case_panic("player AI type", side_ai_type(side));
  153.     break;
  154.     }
  155. }
  156.  
  157. /* Forward a task result to the appropriate AI routine. */
  158.  
  159. void
  160. ai_react_to_task_result(side, unit, task, rslt)
  161. Side *side;
  162. Unit *unit;
  163. Task *task;
  164. int rslt;
  165. {
  166.     switch (side_ai_type(side)) {
  167.       case nobrains:
  168.     break;
  169.       case mplayertype:
  170.     mplayer_react_to_task_result(side, unit, task, rslt);
  171.     break;
  172.       default:
  173.     case_panic("player AI type", side_ai_type(side));
  174.     break;
  175.     }
  176. }
  177.  
  178. int
  179. ai_guide_explorer(side, unit)
  180. Side *side;
  181. Unit *unit;
  182. {
  183.     switch (side_ai_type(side)) {
  184.       case nobrains:
  185.     return FALSE;
  186.       case mplayertype:
  187.     return mplayer_guide_explorer(side, unit);
  188.       default:
  189.     case_panic("player AI type", side_ai_type(side));
  190.           return FALSE;
  191.     }
  192. }
  193.  
  194. int
  195. ai_preferred_build_type(side, unit, plantype)
  196. Side *side;
  197. Unit *unit;
  198. int plantype;
  199. {
  200.     switch (side_ai_type(side)) {
  201.       case nobrains:
  202.     return NONUTYPE;
  203.       case mplayertype:
  204.     return mplayer_preferred_build_type(side, unit, plantype);
  205.       default:
  206.     case_panic("player AI type", side_ai_type(side));
  207.           return NONUTYPE;
  208.     }
  209. }
  210.  
  211. void
  212. ai_finish_movement(side)
  213. Side *side;
  214. {
  215.     switch (side_ai_type(side)) {
  216.       case nobrains:
  217.     break;
  218.       case mplayertype:
  219.     mplayer_finish_movement(side);
  220.     break;
  221.       default:
  222.     case_panic("player AI type", side_ai_type(side));
  223.     break;
  224.     }
  225. }
  226.  
  227. /* Forward a textual message to the appropriate AI routine. */
  228.  
  229. void
  230. ai_receive_message(side, sender, str)
  231. Side *side, *sender;
  232. char *str;
  233. {
  234.     switch (side_ai_type(side)) {
  235.       case nobrains:
  236.     break;
  237.       case mplayertype:
  238.     mplayer_receive_message(side, sender, str);
  239.     break;
  240.       default:
  241.     case_panic("player AI type", side_ai_type(side));
  242.     break;
  243.     }
  244. }
  245.  
  246. void
  247. ai_write_state(fp, side)
  248. FILE *fp;
  249. Side *side;
  250. {
  251.     switch (side_ai_type(side)) {
  252.       case nobrains:
  253.     break;
  254.       case mplayertype:
  255.     mplayer_write_state(fp, side);
  256.     break;
  257.       default:
  258.     case_panic("player AI type", side_ai_type(side));
  259.     break;
  260.     }
  261. }
  262.  
  263. void
  264. ai_read_state(side, data)
  265. Side *side;
  266. Obj *data;
  267. {
  268. #if 0
  269.     /* (should do this eventually - tricky because need to save data until
  270.        AI is actually being set up) */
  271.     side->aidata = (void *) data;
  272. #endif
  273. }
  274.  
  275. int
  276. ai_region_at(side, x, y)
  277. Side *side;
  278. int x, y;
  279. {
  280.     switch (side_ai_type(side)) {
  281.       case nobrains:
  282.     return 0;
  283.       case mplayertype:
  284.     return mplayer_theater_at(side, x, y);
  285.       default:
  286.     case_panic("player AI type", side_ai_type(side));
  287.     return 0;
  288.     }
  289. }
  290.  
  291. char *
  292. ai_at_desig(side, x, y)
  293. Side *side;
  294. int x, y;
  295. {
  296.     switch (side_ai_type(side)) {
  297.       case nobrains:
  298.     return NULL;
  299.       case mplayertype:
  300.     return mplayer_at_desig(side, x, y);
  301.       default:
  302.     case_panic("player AI type", side_ai_type(side));
  303.     return NULL;
  304.     }
  305. }
  306.  
  307. /* (should go elsewhere eventually?) */
  308.  
  309. /* Goal handling. */
  310.  
  311. GoalDefn goaldefns[] = {
  312.  
  313. #undef  DEF_GOAL
  314. #define DEF_GOAL(NAME,code,ARGTYPES) { NAME, ARGTYPES },
  315.  
  316. #include "goal.def"
  317.  
  318.     { NULL, NULL }
  319. };
  320.  
  321.  
  322. /* General handling of goals. */
  323.  
  324. Goal *
  325. create_goal(type, side, tf)
  326. GoalType type;
  327. Side *side;
  328. int tf;
  329. {
  330.     Goal *goal = (Goal *) xmalloc(sizeof(Goal));
  331.  
  332.     goal->type = type;
  333.     goal->side = side;
  334.     goal->tf = tf;
  335.     return goal;
  336. }
  337.  
  338. int
  339. cell_unknown(x, y)
  340. int x, y;
  341. {
  342.     return (!g_see_all() && terrain_view(tmpside, x, y) == UNSEEN);
  343. }
  344.  
  345. int
  346. enemies_present(x, y)
  347. int x, y;
  348. {
  349.     if (g_see_all() /* or x,y under direct observation */) {
  350.         return (unit_at(x, y) != NULL && unit_at(x, y)->side != tmpside);
  351.     } else if (terrain_view(tmpside, x, y) != UNSEEN) {
  352.         return (vside(unit_view(tmpside, x, y)) != side_number(tmpside));
  353.     } else {
  354.         return FALSE;
  355.     }
  356. }
  357.  
  358. /* Test a goal to see if it is true for side, as specified. */
  359.  
  360. int
  361. goal_truth(side, goal)
  362. Side *side;
  363. Goal *goal;
  364. {
  365.     int x, y;
  366.     Side *side2 = NULL;
  367.  
  368.     if (goal == NULL) return 0;
  369.     switch (goal->type) {
  370.       case GOAL_WON_GAME:
  371.     side2 = goal->side;
  372.     return (side2 ? (side_won(side2) ? 100 : -100) : 0);
  373.       case GOAL_LOST_GAME:
  374.     side2 = goal->side;
  375.     return (side2 ? (side_lost(side2) ? 100 : -100) : 0);
  376.       case GOAL_POSITIONS_KNOWN:
  377.     /* what if no enemies present? then this is undefined? */
  378.     /* should goals have preconditions or prerequisites? */
  379.     return 0;
  380.       case GOAL_WORLD_KNOWN:
  381.     tmpside = side;
  382.     for_all_interior_cells(x, y) {
  383.         if (cell_unknown(x, y)) return -100;
  384.     }
  385.     return 100;
  386.       case GOAL_VICINITY_KNOWN:
  387.     tmpside = side;
  388.     if (search_around(goal->args[0], goal->args[1], goal->args[2],
  389.               cell_unknown, &x, &y, 1)) {
  390.         return -100;
  391.     } else {
  392.         return 100;
  393.     }
  394.       case GOAL_VICINITY_HELD:
  395.           tmpside = side;
  396.     if (search_around(goal->args[0], goal->args[1], goal->args[2],
  397.               enemies_present, &x, &y, 1)) {
  398.         return -100;
  399.     } else {
  400.         return 100;
  401.     }
  402.       case GOAL_CELL_OCCUPIED:
  403.     return 0;
  404.       case GOAL_HAS_UNIT_TYPE:
  405.     return 0;
  406.       case GOAL_HAS_UNIT_TYPE_NEAR:
  407.     return 0;
  408.       case GOAL_HAS_MATERIAL_TYPE:
  409.     return 0;
  410.       default:
  411.     case_panic("goal type", goal->type);
  412.     return 0;
  413.     }
  414. }
  415.  
  416. /* (might eventually want another evaluator that guesses at another
  417.    side's goals) */
  418.  
  419. char *goalbuf = NULL;
  420.  
  421. char *
  422. goal_desig(goal)
  423. Goal *goal;
  424. {
  425.     int numargs, i, arg;
  426.     char *argtypes;
  427.  
  428.     if (goal == NULL)
  429.       return "<null goal>";
  430.     if (goalbuf == NULL)
  431.       goalbuf = xmalloc(BUFSIZE);
  432.     sprintf(goalbuf, "<goal s%d %s%s",
  433.         side_number(goal->side), (goal->tf ? "" : "not "),
  434.         goaldefns[goal->type].name);
  435.     argtypes = goaldefns[goal->type].argtypes;
  436.     numargs = strlen(argtypes);
  437.     for (i = 0; i < numargs; ++i) {
  438.     arg = goal->args[i];
  439.     switch (argtypes[i]) {
  440.       case 'h':
  441.         tprintf(goalbuf, "%d", arg);
  442.         break;
  443.       case 'm':
  444.         if (is_material_type(arg))
  445.           tprintf(goalbuf, " %s", m_type_name(arg));
  446.         else
  447.           tprintf(goalbuf, " m%d?", arg);
  448.         break;
  449.       case 'S':
  450.         tprintf(goalbuf, " `%s'", side_desig(side_n(arg)));
  451.         break;
  452.       case 'u':
  453.         if (is_unit_type(arg))
  454.           tprintf(goalbuf, " %s", u_type_name(arg));
  455.         else
  456.           tprintf(goalbuf, " m%d?", arg);
  457.         break;
  458.       case 'U':
  459.         tprintf(goalbuf, " `%s'", unit_desig(find_unit(arg)));
  460.         break;
  461.       case 'w':
  462.         tprintf(goalbuf, " %dx", arg);
  463.         break;
  464.       case 'x':
  465.         tprintf(goalbuf, " %d,", arg);
  466.         break;
  467.       case 'y':
  468.         tprintf(goalbuf, "%d", arg);
  469.         break;
  470.       default:
  471.         tprintf(goalbuf, " %d", arg);
  472.         break;
  473.     }
  474.     }
  475.     strcat(goalbuf, ">");
  476.     return goalbuf;
  477. }
  478.